package com.basic.common.websocket;

import com.alibaba.fastjson2.JSON;
import com.basic.common.constant.CacheConstants;
import com.basic.common.core.domain.AjaxResult;
import com.basic.common.core.domain.entity.SysUser;
import com.basic.common.core.domain.model.LoginUser;
import com.basic.common.core.redis.RedisCacheUtils;
import com.basic.common.enums.BusinessStatus;
import com.basic.common.utils.SecurityUtils;
import com.basic.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 客户端用户集
 *
 * @author zhaoxy_jn@163.com
 */
public class WebSocketUsers {
    /**
     * WebSocketUsers 日志控制器
     */
    private static final Logger logger = LoggerFactory.getLogger(WebSocketUsers.class);

    /**
     * 用户集
     */
    private static final Map<Long, WebSocketSession> USERS = new ConcurrentHashMap<>();

    /**
     * 用户对象集
     */
    private static final Map<Long, LoginUser> LOGIN_USERS = new ConcurrentHashMap<>();

    /**
     * 存储用户
     *
     * @param key     唯一键
     * @param session 用户信息
     */
    public static void put(Long key, WebSocketSession session) {
        USERS.put(key, session);
    }

    /**
     * 存储登录用户信息
     * @param key 唯一键
     * @param loginUser 用户信息
     */
    public static void put(Long key, LoginUser loginUser) {
        LOGIN_USERS.put(key, loginUser);
    }

    /**
     * 移除用户
     *
     * @param session 用户信息
     * @return 移除结果
     */
    public static boolean remove(WebSocketSession session) {
        Long key = null;
        boolean flag = USERS.containsValue(session);
        if (flag) {
            Set<Map.Entry<Long, WebSocketSession>> entries = USERS.entrySet();
            for (Map.Entry<Long, WebSocketSession> entry : entries) {
                WebSocketSession value = entry.getValue();
                if (value.equals(session)) {
                    key = entry.getKey();
                    break;
                }
            }
        } else {
            return true;
        }
        return remove(key);
    }

    /**
     * 移出用户
     *
     * @param key 键
     */
    public static boolean remove(Long key) {
        logger.info("\n 正在移出用户 - {}", key);
        WebSocketSession remove = USERS.remove(key);
        if (remove != null) {
            boolean containsValue = USERS.containsValue(remove);
            logger.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
            return containsValue;
        } else {
            return true;
        }
    }

    /**
     * 移除用户信息
     */
    public static void removeLoginUser(Long key) {
        LOGIN_USERS.remove(key);
    }

    /**
     * 获取在线用户列表
     *
     * @return 返回用户集合
     */
    public static Map<Long, WebSocketSession> getUsers() {
        return USERS;
    }

    /**
     * 群发消息文本消息
     *
     * @param message 消息内容
     * @param status 消息类型 SUCCESS FAIL
     */
    public static void sendMessageToUsersByText(String message, BusinessStatus status) {
        Collection<WebSocketSession> values = USERS.values();
        for (WebSocketSession value : values) {
            sendMessageToUserByText(value, JSON.toJSON(StringUtils.equals("SUCCESS", status.name()) ? AjaxResult.success(message) : AjaxResult.error(message)).toString());
        }
    }

    /**
     * 给指定用户发送消息
     * @param uid 用户唯一编码
     * @param message 消息内容
     * @param status 消息类型 SUCCESS FAIL
     */
    public static void sendMessageToUserByText(Long uid, String message, BusinessStatus status){
        WebSocketSession session = USERS.get(uid);
        if(session != null){
            sendMessageToUserByText(session, JSON.toJSON(StringUtils.equals("SUCCESS", status.name()) ? AjaxResult.success(message) : AjaxResult.error(message)).toString());
        }
    }

    /**
     * 给当前用户和当前用户祖级发送文本消息
     * @param uid 用户唯一编码
     * @param message 消息内容
     * @param status 消息类型 SUCCESS FAIL
     */
    public static void sendMessageToSuperiorByText(Long uid,String message, BusinessStatus status){
        // 获取此用户部门层级关系
        SysUser sysUser = LOGIN_USERS.get(uid).getUser();
        String ancestors = sysUser.getDept().getAncestors();
        // 给自己发消息
        sendMessageToUserByText(uid,JSON.toJSON(message).toString(),status);

        Collection<String> keys = RedisCacheUtils.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        StringBuilder messageBuilder = new StringBuilder();
        for (String key : keys)
        {
            LoginUser user = RedisCacheUtils.getCacheObject(key.substring(key.indexOf(":")+1));
            // 发送给此用户的上级部门用户
            if(Arrays.asList(ancestors.split(",")).contains(user.getDeptId().toString())){
                if (!Objects.equals(user.getUserId(), uid)) {
                    messageBuilder.append("员工：【").append(sysUser.getUserName()).append("】，");
                    messageBuilder.append(message);
                }
                sendMessageToUserByText(user.getUserId(),JSON.toJSON(messageBuilder).toString(),status);
                messageBuilder.setLength(0);
            }
        }
    }

    /**
     * 发送文本消息
     *
     * @param session session
     * @param message 消息内容
     */
    public static void sendMessageToUserByText(WebSocketSession session, String message) {
        if (session != null) {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                logger.error("\n[发送消息异常]", e);
            }
        } else {
            logger.info("\n[您已离线]");
        }
    }
}
